package utils

import (
	"math"
)

// LevenshteinDistance 计算两个字符串的编辑距离
func LevenshteinDistance(s1, s2 string) int {
	r1, r2 := []rune(s1), []rune(s2)
	rows := len(r1) + 1
	cols := len(r2) + 1

	d := make([][]int, rows)
	for i := range d {
		d[i] = make([]int, cols)
	}

	for i := 1; i < rows; i++ {
		d[i][0] = i
	}
	for j := 1; j < cols; j++ {
		d[0][j] = j
	}

	for i := 1; i < rows; i++ {
		for j := 1; j < cols; j++ {
			cost := 0
			if r1[i-1] != r2[j-1] {
				cost = 1
			}
			d[i][j] = min(
				min(d[i-1][j]+1, d[i][j-1]+1),
				d[i-1][j-1]+cost,
			)
		}
	}

	return d[rows-1][cols-1]
}

// StringSimilarity 计算字符串相似度 (0-1之间，1表示完全相同)
func StringSimilarity(s1, s2 string) float64 {
	if s1 == s2 {
		return 1.0
	}

	maxLen := math.Max(float64(len([]rune(s1))), float64(len([]rune(s2))))
	if maxLen == 0 {
		return 1.0
	}

	distance := LevenshteinDistance(s1, s2)
	return 1.0 - float64(distance)/maxLen
}

// FindBestMatch 在多个候选项中找到与目标字符串最相似的匹配
func FindBestMatch(target string, candidates []string) (string, float64) {
	if len(candidates) == 0 {
		return "", 0.0
	}

	bestMatch := candidates[0]
	bestScore := StringSimilarity(target, candidates[0])

	for i := 1; i < len(candidates); i++ {
		score := StringSimilarity(target, candidates[i])
		if score > bestScore {
			bestScore = score
			bestMatch = candidates[i]
		}
	}

	return bestMatch, bestScore
}

// MatchResult 匹配结果结构体
type MatchResult struct {
	Text  string  `json:"text"`
	Score float64 `json:"score"`
}

// FindBestMatches 返回所有候选项的相似度分数，按分数降序排列
func FindBestMatches(target string, candidates []string) []MatchResult {
	results := make([]MatchResult, len(candidates))

	for i, candidate := range candidates {
		score := StringSimilarity(target, candidate)
		results[i] = MatchResult{
			Text:  candidate,
			Score: score,
		}
	}

	// 按分数降序排序
	for i := 0; i < len(results)-1; i++ {
		for j := i + 1; j < len(results); j++ {
			if results[i].Score < results[j].Score {
				results[i], results[j] = results[j], results[i]
			}
		}
	}

	return results
}

// min 辅助函数
func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}
